package com.sum.tea.xinlian.viewmodel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.pow.api.cls.RfidPower
import com.power.OtherPower
import com.sum.tea.contants.AppConfig
import com.uhf.api.cls.Reader
import com.zguang.api.comm.linuxcomm
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

class SubDebugViewModel(application: Application) : AndroidViewModel(application) {

    private var mAppConfig: AppConfig = AppConfig()
    private var lreader: linuxcomm? = null
    private var isNewOpen: Boolean = false
    private var isRun: Boolean = false

    private val _receivedData = MutableLiveData("")
    val receivedData: MutableLiveData<String> get() = _receivedData

    private val _toastMessages = MutableLiveData("")
    val toastMessages: MutableLiveData<String> get() = _toastMessages

    private var mess: String = ""
    private var st: Long = 0

    private val strBaud = arrayOf(
        "4800", "9600", "19200", "38400",
        "57600", "115200", "230400", "460800",
        "921600"
    )

    private var strPdaType: Array<String>? = null

    fun initialize(application: Application) {
        // Initialize AppConfig and other configurations if needed
        mAppConfig = AppConfig()
        strPdaType = RfidPower.getPdaPlat()
    }

    fun getPdaTypes(): Array<String> {
        return strPdaType ?: arrayOf()
    }

    fun getBaudRates(): Array<String> {
        return strBaud
    }

    fun hasInitialized(): Boolean {
        return mAppConfig.haveinit
    }

    fun getDevPath(): String {
        return mAppConfig.Rpower.GetDevPath()
    }

    fun open(addr: String, baudRate: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            lreader = linuxcomm()
            val re = lreader?.OpenComm(addr, baudRate) ?: -1
            isNewOpen = re == 0
            launch(Dispatchers.Main) {
                if (isNewOpen) {
                    _toastMessages.value = "open: $re"
                } else {
                    _toastMessages.value = "open: $re"
                }
            }
        }
    }

    fun close() {
        viewModelScope.launch(Dispatchers.IO) {
            lreader?.CloseComm()
            isNewOpen = false
            launch(Dispatchers.Main) {
                _toastMessages.value = "Connection closed."
            }
        }
    }

    fun sendData(strVal: String) {
        if (strVal.contains(" ")) {
            viewModelScope.launch(Dispatchers.Main) {
                _toastMessages.value = "open: $strVal no all hex chars"
            }
            return
        }

        viewModelScope.launch(Dispatchers.IO) {
            val buf = ByteArray(strVal.length / 2)
            mAppConfig.Mreader.Str2Hex(strVal, strVal.length, buf)
            if (isNewOpen) {
                lreader?.SendDatab(buf, buf.size)
            } else {
                mAppConfig.Mreader.DataTransportSend(buf, buf.size, if (strVal.length <= 4) 200 else 1000)
            }
            st = System.currentTimeMillis()
        }
    }

    fun startReceiving() {
        isRun = true
        viewModelScope.launch(Dispatchers.IO) {
            while (isRun) {
                var temp = ""
                if (isNewOpen) {
                    val readBuffer = ByteArray(255)
                    val hreadCount = IntArray(1)
                    val re = lreader?.RevData_nonblockb(readBuffer, hreadCount) ?: -1
                    if (hreadCount[0] > 0) {
                        temp += bytesHexStr(readBuffer, hreadCount[0])
                        temp = "L:${temp.length / 2} $temp T:${System.currentTimeMillis() - st}"
                    }
                    if (re > 0) {
                        temp = "E:$re T:${System.currentTimeMillis() - st}"
                    }
                } else {
                    val part1 = ByteArray(3)
                    val re = mAppConfig.Mreader.DataTransportRecv(part1, part1.size, 500)
                    if (re == 0 && part1[2] != 0x00.toByte()) {
                        temp += bytesHexStr(part1, 3)
                        val l = (part1[1].toInt() and 0xff) + 4
                        val part2 = ByteArray(l)
                        val re2 = mAppConfig.Mreader.DataTransportRecv(part2, part2.size, 1000)
                        if (re2 == 0) {
                            temp += bytesHexStr(part2, part2.size)
                        }
                        temp = "L:${temp.length / 2} $temp T:${System.currentTimeMillis()}"
                    }
                }

                if (temp.isNotEmpty()) {
                    mess = if (mess.length > 1000) mess.substring(900) else mess
                    mess += "$temp\r\n"
                    _receivedData.value = mess
                }
            }
        }
    }

    fun stopReceiving() {
        isRun = false
    }

    fun powerUp() {
        viewModelScope.launch(Dispatchers.IO) {
            // val blen = mAppConfig.Rpower.PowerUp()
            val blen = true
            OtherPower.oPowerUp() // modify by hejiang
            launch(Dispatchers.Main) {
                _toastMessages.value = "${AppConfig.Constr_mainpu}$blen"
            }
        }
    }

    fun powerDown() {
        viewModelScope.launch(Dispatchers.IO) {
            // val blen = mAppConfig.Rpower.PowerDown()
            val blen = true
            OtherPower.oPowerDown() // modify by hejiang
            launch(Dispatchers.Main) {
                _toastMessages.value = "${AppConfig.action_db_down}$blen"
            }
        }
    }

    fun setBaudRate(baudRate: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            if (isNewOpen) {
                launch(Dispatchers.Main) {
                    _toastMessages.value = "must connect to reader"
                }
                return@launch
            }
            val dp = mAppConfig.Mreader.Default_Param().apply {
                isdefault = false
                key = Reader.Mtr_Param.MTR_PARAM_SAVEINMODULE_BAUD
                `val` = baudRate
            }
            val re = mAppConfig.Mreader.ParamSet(Reader.Mtr_Param.MTR_PARAM_SAVEINMODULE, dp)
            launch(Dispatchers.Main) {
                if (re == Reader.READER_ERR.MT_OK_ERR) {
                    _toastMessages.value = "ok, power down for reader, reconnect"
                } else {
                    _toastMessages.value = "operate failed"
                }
            }
        }
    }

    fun clearReceivedData() {
        mess = ""
        viewModelScope.launch(Dispatchers.Main) {
            _receivedData.value = mess
        }
    }

    private fun bytesHexStr(bArray: ByteArray, length: Int): String {
        val sb = StringBuilder(bArray.size)
        for (i in 0 until length) {
            val sTemp = Integer.toHexString(bArray[i].toInt() and 0xFF)
            if (sTemp.length < 2) sb.append('0')
            sb.append(sTemp.uppercase())
        }
        return sb.toString()
    }
}